package models

import (
	"gorm.io/gorm"
	"interview/pkg/utils"
	"time"
)

// Membership 会员资格，一个用户可以有多个会员资格记录（包含了历史会员资格记录，且记录之间不能存在有效期的重合）
type Membership struct {
	Model
	UserOpenID       string        `gorm:"comment:'用户openid,加密存储';column:'user_open_id';" json:"userOpenID"`
	MembershipType   int           `gorm:"type:tinyint(4);default:0;comment:'会员类别(0游客/1普通积分充值vip/2月度svip/3季度svip/4半年svip/5年度svip)'" json:"membershipType"`
	MembershipPoints int           `gorm:"comment:'用户积分';default:20" json:"membershipPoints"`
	StartDate        *LocalTime    `gorm:"comment:'会员身份开始时间'" json:"startDate"`
	EndDate          *LocalTime    `gorm:"comment:'会员身份结束时间'" json:"endDate"`
	Duration         time.Duration `gorm:"comment:'有效期'" json:"duration"`
	// TODO 会员资格过期后续采用定时任务来实现？
	Status     *bool  `gorm:"type:'tinyint(1)';default:1;comment:'会员资格状态(1正常/0过期)'" json:"status"`
	ActiveCode string `gorm:"unique;comment:'会员充值激活码，加密存储'" json:"activeCode"`
}

func (m Membership) AfterFind(db *gorm.DB) (err error) {
	if m.UserOpenID != "" {
		m.UserOpenID = utils.AesDecrypt(m.UserOpenID)
	}
	if m.ActiveCode != "" {
		m.ActiveCode = utils.AesDecrypt(m.ActiveCode)
	}
	return
}

func (m Membership) BeforeSave(db *gorm.DB) (err error) {
	if m.UserOpenID != "" {
		m.UserOpenID = utils.AesEncrypt(m.UserOpenID)
	}
	if m.ActiveCode != "" {
		m.ActiveCode = utils.AesEncrypt(m.ActiveCode)
	}
	return
}

// TableName 修改默认表名
func (Membership) TableName() string {
	return TableName("membership")
}

func CreateMembership(data map[string]interface{}) (uint, error) {
	tx := db.Begin()
	defer func() {
		if e := recover(); e != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	start, end := data["start"].(LocalTime), data["end"].(LocalTime)
	m := Membership{
		UserOpenID:       data["openID"].(string),
		MembershipType:   data["membershipType"].(int),
		MembershipPoints: data["membershipPoints"].(int),
		StartDate:        &start,
		EndDate:          &end,
		Duration:         data["duration"].(time.Duration),
		ActiveCode:       data["activeCode"].(string),
	}

	tx.Create(&m)

	curM, err := FindUserByOpenID(m.UserOpenID)
	if err != nil {
		return 0, err
	}
	userData := map[string]interface{}{
		"current_membership_type": m.MembershipType,
		"current_end_date":        m.MembershipPoints,
	}

	if curM.CurrentEndDate == nil {
		userData["current_end_date"] = m.EndDate
	} else {
		// 续期
		userData["current_end_date"] = curM.CurrentEndDate.Add(m.Duration)
	}

	_, err = UpdateUserByOpenID(m.UserOpenID, userData)
	if err != nil {
		return 0, err
	}

	return 0, nil
}

func UpdateMembership(id uint, data map[string]interface{}) (uint, error) {

	return id, db.Model(&Membership{}).Where("id", id).Updates(data).Error
}

func FindLatestMembershipByOpenID(openID string) (*Membership, error) {
	return findLatestMembershipByOpenID(openID)
}

func findLatestMembershipByOpenID(openID string) (*Membership, error) {
	var m Membership
	err := db.Model(&m).Where("open_id", openID).Order("id desc").First(&m).Error
	return &m, err
}

func FindMembershipList(openID string) ([]*Membership, error) {
	var m []*Membership
	base := db.Model(&m)
	if openID != "" {
		base = base.Where("open_id", openID)
	}
	base = base.Order("id desc").Find(&m)
	return m, base.Error
}
